package com.ssd.handler;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.ssd.annotation.PayChannel;
import com.ssd.api.payment.dto.enums.PayChannelEnum;

import java.util.Map;

/**
 * Handler工厂，用于获取指定类型的具体渠道的实例对象
 */
public class HandlerFactory {

    // 私有构造方法，防止实例化
    private HandlerFactory() {

    }

    /**
     * 根据支付渠道枚举和处理程序类获取相应的处理程序实例
     *
     * @param payChannel 支付渠道枚举
     * @param handler 处理程序的类类型
     * @param <T> 处理程序的泛型类型
     * @return 对应支付渠道的处理程序实例，如果找不到则返回null
     */
    public static <T> T get(PayChannelEnum payChannel, Class<T> handler) {
        // 获取Spring上下文中所有指定类型的Bean
        Map<String, T> beans = SpringUtil.getBeansOfType(handler);
        for (Map.Entry<String, T> entry : beans.entrySet()) {
            // 检查Bean类是否有PayChannel注解
            PayChannel payChannelAnnotation = entry.getValue().getClass().getAnnotation(PayChannel.class);
            // 如果注解存在且注解的type属性与payChannel参数值相等，则返回该Bean实例
            if (ObjectUtil.isNotEmpty(payChannelAnnotation) && ObjectUtil.equal(payChannel, payChannelAnnotation.type())) {
                return entry.getValue();
            }
        }
        // 如果没有找到匹配的处理程序实例，则返回null
        return null;
    }

    /**
     * 根据支付渠道字符串和处理程序类获取相应的处理程序实例
     *
     * @param payChannel 支付渠道字符串
     * @param handler 处理程序的类类型
     * @param <T> 处理程序的泛型类型
     * @return 对应支付渠道的处理程序实例，如果找不到则返回null
     */
    public static <T> T get(String payChannel, Class<T> handler) {
        // 将支付渠道字符串转换为枚举，并调用重载的get方法
        return get(PayChannelEnum.valueOf(payChannel), handler);
    }
}

